package com.ydlclass.utils.zookeeper;

import com.ydlclass.Constant;
import com.ydlclass.exceptions.ZookeeperException;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @Author duWenJian
 * @Date 2024/2/12 15:34
 * @Version 1.0
 */
@Slf4j
public class ZookeeperUtils {
    /**
     * 使用默认的配置来创建zookeeper实例
     * @return
     */
    public static ZooKeeper createZookeeper() {
        String connectString = Constant.DEFAULT_ZK_CONNECT;
        int timeOut = Constant.TIME_OUT;
        ZooKeeper zookeeper = createZookeeper(connectString, timeOut);
        return zookeeper;
    }

    /**
     * 可以自己传参来进行创建zookeeper实例
     * @param connectString
     * @param timeOut
     * @return
     */
    public static ZooKeeper createZookeeper(String connectString , int timeOut) {

            CountDownLatch countDownLatch = new CountDownLatch(1);
            try {
            final ZooKeeper zooKeeper = new ZooKeeper(connectString, timeOut, event -> {
                if (event.getState() == Watcher.Event.KeeperState.SyncConnected) {
                    log.debug("连接成功");
                    countDownLatch.countDown();
                }
            });
            countDownLatch.await();
            return zooKeeper;
        } catch (IOException | InterruptedException e) {
            throw new ZookeeperException();
        }
    }

    /**
     * 创建一个zookeeper节点的工具方法
     * @param zooKeeper zookeeper实例
     * @param zookeeperNode 节点
     * @param watcher Watcher监视器
     * @param createMode 创建模式(临时节点还是持久节点)
     * @return true 创建成功 false 创建失败
     */
    public static boolean createNode(ZooKeeper zooKeeper,ZookeeperNode zookeeperNode,Watcher watcher, CreateMode createMode){
            try {
                if (zooKeeper.exists(zookeeperNode.getNodePath(),watcher) == null){
                    String result = zooKeeper.create(zookeeperNode.getNodePath(), zookeeperNode.getData(),
                            ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);
                    log.info("节点:{}创建成功",result);
                    return true;
                } else {
                    log.info("节点:{}已存在,无需创建",zookeeperNode.getNodePath());
                }
            } catch (KeeperException | InterruptedException e) {
                log.error("创建基础目录时发生异常:{}",e);
                throw new ZookeeperException();
            }
            return false;
    }

    /**
     * zookeeper关闭的方法 zookeeper实例
     * @param zooKeeper
     */
    public static void shutDownZookeeper(ZooKeeper zooKeeper){
        try {
            zooKeeper.close();
        } catch (InterruptedException e) {
            throw new ZookeeperException();
        }
    }

    /**
     * 判断节点是否存在
     * @param zk zookeeper实例
     * @param node node节点
     * @param watcher watcher监视器
     * @return ！= null 表示存在返回true , 否则不存在
     */
    public static boolean exists(ZooKeeper zk , String node , Watcher watcher) {
        try {
            return zk.exists(node,watcher) != null;
        } catch (KeeperException | InterruptedException e) {
            log.error("判断节点{}是否存在时发生{}异常",node,e);
            throw new ZookeeperException();
        }
    }

    /**
     * 查询节点的子元素
     * @param zooKeeper zk实例
     * @param serviceNode 服务节点
     * @return 子节点列表
     */
    public static List<String> getChildren(ZooKeeper zooKeeper, String serviceNode, Watcher watcher) {
        try {
            return zooKeeper.getChildren(serviceNode, watcher);
        } catch (KeeperException | InterruptedException e) {
            log.error("获取节点{}的子元素时发生异常{}",serviceNode,e);
            throw new ZookeeperException(e);
        }
    }
}
